package com.mouse.magent.common.net;

import com.mouse.magent.common.handler.BaseChannelInitializer;
import com.mouse.magent.common.handler.BaseHandler;
import com.mouse.magent.common.handler.ClientHandler;
import com.mouse.magent.common.protocol.Command;
import com.mouse.magent.common.service.BaseChannelInit;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;

@Slf4j
public class TcpClient {
    @Getter
    private Channel channel;
    @Getter
    private DefaultChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    public void connect(String host, int port, ChannelInitializer channelInitializer) throws Exception {
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(workerGroup);
            b.channel(NioSocketChannel.class);
            b.option(ChannelOption.SO_KEEPALIVE, true);
            b.handler(channelInitializer);
            ChannelFuture channelFuture = b.connect(host, port);
            channel = channelFuture.sync().channel();
            channel.closeFuture().addListener((ChannelFutureListener) future -> {
                Thread.sleep(30 * 1000);
                System.out.println(host + ":" + port + " 连接失败");
                connect(host, port, channelInitializer);
            });
        } catch (Exception e) {
            Thread.sleep(30 * 1000);
            System.out.println(host + ":" + port + " 连接失败");
            workerGroup.shutdownGracefully();
        }
    }

    public void connect(String host, int port, Command connectCommand, BaseChannelInit channelInit) throws InterruptedException, IOException {
        BaseHandler handler = new ClientHandler(connectCommand);
        connect(host, port, handler, channelInit);
    }

    public void connect(String host, int port, BaseHandler handler, BaseChannelInit channelInit) throws InterruptedException, IOException {
        handler.setCommandActionList(channelInit.getMessageAction());
        handler.setChannelGroup(channelGroup);
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();
        BaseChannelInitializer channelInitializer = new BaseChannelInitializer(handler);
        while (true) {
            try {
                Bootstrap b = new Bootstrap();
                b.group(workerGroup);
                b.channel(NioSocketChannel.class);
                b.option(ChannelOption.SO_KEEPALIVE, true);
                b.handler(channelInitializer);

                channel = b.connect(host, port).sync().channel();
                channel.closeFuture().addListener(future -> {
                    workerGroup.shutdownGracefully();
                    log.error("连接断开,等待30秒重试");
                    Thread.sleep(30 * 1000);
                    connect(host, port, handler, channelInit);
                });
                break;
            } catch (Exception e) {
                workerGroup.shutdownGracefully();
                log.error("连接断开,等待30秒重试");
                Thread.sleep(30 * 1000);
            }
        }

    }

    public ChannelFuture connectCustom(String host, int port, ChannelInitializer channelInitializer) throws Exception {
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();
        Bootstrap b = new Bootstrap();
        b.group(workerGroup);
        b.channel(NioSocketChannel.class);
        b.handler(channelInitializer);
        ChannelFuture channelFuture = b.connect(host, port);
        return channelFuture;
    }
}